#pragma once

#ifndef _introp_
#define _introp_

#define _CRT_SECURE_NO_DEPRECATE

//#include "pch.h"
#include <stdlib.h>
#include <cstdio>
#include <stdio.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <cstring>


#pragma region 整型

/// <summary>
/// 输入参数，返回结果
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
extern "C" __declspec(dllexport)
int Add0(int a, int b)
{
	return a + b;
};

/// <summary>
/// 输入参数，返回结果放到指定地址内
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
extern "C" __declspec(dllexport)
void Add1(int a, int b, int* c)
{
	*c = a + b;
};

/// <summary>
/// 输入参数指针，返回结果放到指定地址
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
extern "C" __declspec(dllexport)
void Add2(int* a, int* b, int* c)
{
	*c = *a + *b;
};

/// <summary>
/// 输入参数指针，返回结果放到指定地址
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
extern "C" __declspec(dllexport)
void Add3(int& a, int& b, int& c)
{
	c = a + b;
};

#pragma endregion

#pragma region 数组

/// <summary>
/// 输入数组指针，输出求和结果
/// </summary>
/// <param name="a"></param>
/// <param name="len"></param>
/// <param name="b"></param>
extern "C" __declspec(dllexport)
void Sum(int* a, int len, int* b)
{
	if (len <= 0)
		return;
	*b = 0;
	for (int i = 0; i < len; i++)
	{
		*b = *b + a[i];
	}
};

/// <summary>
/// 输入数组，输出求和结果
/// </summary>
/// <param name="a"></param>
/// <param name="len"></param>
/// <param name="b"></param>
extern "C" __declspec(dllexport)
void Sum2(int a[], int len, int* b)
{
	if (len <= 0)
		return;
	*b = 0;
	for (int i = 0; i < len; i++)
	{
		*b = *b + a[i];
	}
};

/// <summary>
/// 输出数组,需要C#申请空间,指针为空时，仅输出空间大小
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="range"></param>
/// <param name="len"></param>
extern "C" __declspec(dllexport)
void Range(int start, int end, int* range, int* len)
{
	*len = 0;
	if (start > end)
		return;
	*len = end - start + 1;
	if (range == NULL)
	{
		return;
	}
	for (int i = start; i <= end; i++)
	{
		range[i - start] = i;
	}
};

/// <summary>
/// 排序，C#传入要排序的数组和要输出的数组
/// </summary>
/// <param name="a"></param>
/// <param name="len"></param>
/// <param name="b"></param>
extern "C" __declspec(dllexport)
void Sort(int* a, int len, int* b)
{
	if (len <= 1)
		return;
	for (int i = 0; i < len; i++)
	{
		b[i] = a[i];
	}
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (b[j] > b[j + 1])
			{
				int t = b[j];
				b[j] = b[j + 1];
				b[j + 1] = t;
			}
		}
	}
};

#pragma endregion

//字符串
#pragma region 

/*
声明的位置不需要extern
*/

/// <summary>
/// 将输入字符串转换为大写后，输出
/// </summary>
/// <param name="input"></param>
/// <param name="len"></param>
/// <param name="output"></param>
extern "C" __declspec(dllexport)
void Upper(char* input, char* output)
{
	if (input == NULL || output == NULL)
		return;
	int d = 'A' - 'a';
	int i = 0;
	while (input[i] != '\0')
	{
		if (input[i] >= 'a' && input[i] <= 'z')
		{
			output[i] = input[i] + d;
		}
		else
		{
			output[i] = input[i];
		}
		i++;
	}
	output[i] = input[i];
}

/// <summary>
/// 将输入子字符串原地改为小写后输出
/// </summary>
/// <param name="input"></param>
/// <param name="len"></param>
extern "C" __declspec(dllexport)
void Lower(char* input)
{
	if (input == NULL)
		return;
	int d = 'a' - 'A';
	int i = 0;
	while (input[i] != '\0')
	{
		if (input[i] >= 'A' && input[i] <= 'Z')
		{
			input[i] = input[i] + d;
		}
		else
		{
			input[i] = input[i];
		}
		i++;
	}
}

extern "C" __declspec(dllexport)
void Lower2(char input[])
{
	if (input == NULL)
		return;
	int d = 'a' - 'A';
	int i = 0;
	while (input[i] != '\0')
	{
		if (input[i] >= 'A' && input[i] <= 'Z')
		{
			input[i] = input[i] + d;
		}
		else
		{
			input[i] = input[i];
		}
		i++;
	}
}

/// <summary>
/// 获取错误代码的文字描述
/// </summary>
/// <param name="errorCode"></param>
/// <param name="info"></param>
/// <param name="len"></param>
extern "C" __declspec(dllexport)
void GetErrorInfoEx(int errorCode, char* info, int& len)
{
	const char* msg;
	switch (errorCode)
	{
	case 0:
		msg = "成功";
		break;
	case 1:
		msg = "错误代码1";
		break;
	case 2:
		msg = "错误代码002";
		break;
	default:
		msg = "未知的错误代码x";
		break;
	}
	if (info == NULL)
	{
		len = strlen(msg);
	}
	else
	{
		int m = std::min(len, (int)std::strlen(msg));
		for (int i = 0; i < m; i++)
		{
			info[i] = msg[i];
		}
		info[m] = '\0'; //需要指定最后一个字符为结束字符
	}
}

#include <iostream>

/// <summary>
/// 打印字符串
/// </summary>
/// <param name="cinput"></param>
extern "C" __declspec(dllexport)
void PrintfAnsiString(char* cinput)
{
	std::string input = std::string(cinput);
	if (input.length() <= 0)
	{
		printf("CPP--->Ansi00:%s\n", "<NULL>");
	}
	else
	{
		const char* cstr = input.c_str();
		printf("CPP--->Ansi00:%s,len:%d\n", cstr, strlen(cstr));
	}
}

extern "C" __declspec(dllexport)
void PrintfAnsi(char* input, int len)
{
	if (len <= 0)
		return;
	if (input == NULL)
	{
		printf("CPP--->Ansi11:%s\n", "<NULL>");
	}
	else
	{
		printf("CPP--->Ansi11:%s,len:%d\n", input, len);
	}
}

#pragma endregion

#pragma region class

class Point
{
private:
	float _x;
	float _y;
public:
	Point(float x, float y)
	{
		_x = x;
		_y = y;
	};
	~Point() {}
	void setX(float x) { _x = x; }
	void setY(float y) { _y = y; }
	float getX() { return _x; }
	float getY() { return _y; }
	float Range() { return sqrt(pow(_x, 2) + pow(_y, 2)); }
	float Range(Point* p2) 
	{
		float dx = _x - p2->getX();
		float dy = _y - p2->getY();
		return sqrt(pow(dx, 2) + pow(dy, 2));
	}
};

/// <summary>
/// 获取点实例
/// </summary>
/// <param name="ptr"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
extern "C" __declspec(dllexport)
int CreatePoint(Point * ptr, float x, float y)
{
	Point* p = new Point(x, y);//不能自动销毁，所以使用new关键词
	*ptr = *p; //修改指针内容，不能修改指针本身，即使用 `ptr=p;`
	return 0;
};

//extern "C" __declspec(dllexport)
//int DeletePoint(Point * p)
//{
//	if (p == nullptr)
//		return -1;
//	delete p;
//	return 0;
//};
//
//extern "C" __declspec(dllexport)
//int DeletePoint2(Point& p)
//{
//	if (&p == nullptr)
//		return -1;
//	delete &p;
//	return 0;
//};

/// <summary>
/// 计算到原点的距离
/// </summary>
/// <param name="ptr"></param>
/// <returns></returns>
extern "C" __declspec(dllexport)
float Distance(Point & ptr)
{
	if (&ptr == nullptr)
		return -1;
	return ptr.Range();
};

/// <summary>
/// 计算两个点之间的距离
/// </summary>
/// <param name="ptr1"></param>
/// <param name="ptr2"></param>
/// <returns></returns>
extern "C" __declspec(dllexport)
float Distance2(Point * ptr1, Point * ptr2)
{
	if (ptr1 == nullptr || ptr2 == nullptr)
		return -1;
	return ptr1->Range(ptr2);
};

#pragma endregion

#pragma region 结构体

struct IpInfo
{
	int IP;
	int Mask;
};

struct Name
{
	char v0;
	char v1;
	char v2;
	char v3;
	char v4;
};

struct host
{
	IpInfo ip;
	Name name;
};

void printIp(IpInfo* p)
{
	unsigned char ip[4];
	unsigned char mask[4];
	ip[0] = (p->IP & 0xFF000000) >> 24;
	ip[1] = (p->IP & 0xFF0000) >> 16;
	ip[2] = (p->IP & 0xFF00) >> 8;
	ip[3] = (p->IP & 0xFF) >> 0;

	mask[0] = (p->Mask & 0xFF000000) >> 24;
	mask[1] = (p->Mask & 0xFF0000) >> 16;
	mask[2] = (p->Mask & 0xFF00) >> 8;
	mask[3] = (p->Mask & 0xFF) >> 0;
	//输出IP地址和子网掩码
	printf("\tIP:%d.%d.%d.%d;Mask:%d.%d.%d.%d \n"
		, ip[0], ip[1], ip[2], ip[3]
		, mask[0], mask[1], mask[2], mask[3]
	);
}

extern "C" __declspec(dllexport)
int Input(int flag, void* ptr, int count)
{
	if (flag == 0)
	{
		IpInfo* p = (IpInfo*)ptr;
		printIp(p);
		return 0;
	}
	else if (flag == 1)
	{
		host* p = (host*)ptr;
		printf("host name:%c%c%c%c", p->name.v0, p->name.v1, p->name.v2, p->name.v3, p->name.v4);
		printIp(&(p->ip));
		return 0;
	}
	return 1;
};

#pragma endregion


#endif // !_introp_
